package userservice

import (
	"bytes"
	"context"
	"encoding/json"
	"errors"
	"fmt"
	"github.com/google/uuid"
	"io/ioutil"
	"log"
	"net/http"
	"time"
	"vpn-management-server/config"

	"vpn-management-server/logger"
	"vpn-management-server/network"
	"vpn-management-server/security"
	"vpn-management-server/security/code"
	"vpn-management-server/security/crypto/cert"
	"vpn-management-server/src/dao/userdao"
	"vpn-management-server/src/model/identitymodel"
	"vpn-management-server/src/model/usermodel"
	"vpn-management-server/src/service/rgroupservice"
	"vpn-management-server/src/service/ruleservice"
	"vpn-management-server/utils"
)

var (
	connectToBCFailErr = errors.New("connect to blockchain fail")
	sendRequestFailErr = errors.New("send data to blockchain fail")
	getResponseFailErr = errors.New("get response data from blockchain fail")
)

var minSDKConfig *config.MinSDKConfig

func Init(sdkConfig config.MinSDKConfig) {
	minSDKConfig = &sdkConfig
}

func ValidateEmailService(ctx context.Context, email string) bool {
	return !userdao.HasUserByEmail(email)
}

func DeleteUserService(uid int) error {
	err := userdao.DeleteUserByID(uid)
	if err != nil {
		logger.Logger.Errorf("delete user fail")
		return err
	}
	// TODO 删除分配给用户的规则和规则组
	err = rgroupservice.DepriveAllRGroupFromUserService(uid)
	if err != nil {
		logger.Logger.Error("deprive user rgroup fail")
		return err
	}
	err = ruleservice.DepriveAllRuleFromUserService(uid)
	if err != nil {
		logger.Logger.Error("delete user rule fail")
		return err
	}
	return nil
}

func VerifyCertificateService(user *usermodel.User, signature []byte) bool {
	var Cert cert.Certificate
	err := Cert.FromPem(user.Certificate, []byte("123456"), security.SM4ECB)
	if err != nil {
		logger.Logger.Error("parse cert fail,err:", err)
		return false
	}
	IsValid, _ := Cert.PublicKey.Verify([]byte(user.Name), signature, nil)
	if !IsValid {
		logger.Logger.Error("verify signature fail")
		return false
	}
	return true
}

func CheckWhiteList(phone string) bool {
	conn := network.GetBCSSLConn()
	if conn == nil {
		logger.Logger.Error("connect to blockchain fail")
		return false
	}
	var request network.NetRequest
	data := map[string]string{"PhoneNumber": "18512345678", "IDCardNumber": "123456789"}
	jsonData, _ := json.Marshal(data)
	logger.Logger.Debug("jsonData:", jsonData)
	request.Type = "whitelist"
	request.Command = "getAllWhitelist"
	request.Method = "POST"
	request.Parameters = jsonData
	err := network.SendRequest(&request, conn)
	if err != nil {
		logger.Logger.Error("send request fail")
		return false
	}
	res, err := network.GetResponse(conn)

	if err != nil {
		logger.Logger.Error("get response from blockchain fail")
		return false
	}
	var items []usermodel.Item
	err = json.Unmarshal(res.Data, &items)
	if err != nil {
		fmt.Println("JSON unmarshal error:", err)
		return false
	}
	found := false
	for _, item := range items {
		if item.PhoneNumber == phone {
			found = true
			break
		}
	}
	if found {
		fmt.Println("True")
		return true
	}
	fmt.Println("False")
	return false

}

func AddIdentityService(user *usermodel.User) bool {
	conn := network.GetBCSSLConn()
	if conn == nil {
		logger.Logger.Error("connect to blockchain fail")
		return false
	}
	var request network.NetRequest
	var identity identitymodel.Identity
	identity.IdentityIdentifier = "/" + user.Name
	identity.Pubkey = user.Pubkey
	identity.Passwd = "123456" // 默认lock证书的密码
	identity.Type = "identity-act"
	identity.Command = "Registry"
	data, _ := json.Marshal(identity)
	logger.Logger.Debug("identity:", identity)
	logger.Logger.Debug("pubKey length:", len(identity.Pubkey))
	request.Type = "identity-act"
	request.Command = "Registry"
	request.Method = "POST"
	request.Parameters = data
	err := network.SendRequest(&request, conn)
	if err != nil {
		logger.Logger.Error("send request fail")
		return false
	}
	res, err := network.GetResponse(conn)
	if err != nil {
		logger.Logger.Error("get response from blockchain fail")
		return false
	}
	if res.Code == code.SUCCESS {
		_ = json.Unmarshal(res.Data, &identity)
		user.Certificate = identity.Cert
		return true
	} else {
		return false
	}
}

func DeleteUserIdentityFromBCSSL(IdentityIdentifier string) error {
	var request = network.NewNetRequest()
	request.Type = "identity-act"
	request.Command = "RevokeRegistry"
	request.Method = "GET"
	conn := network.GetBCSSLConn()
	if conn == nil {
		logger.Logger.Error("connect to blockchain fail")
		return connectToBCFailErr
	}

	logger.Logger.Debug("send info:", IdentityIdentifier)
	var identity = usermodel.IdentityIdentifier{}
	identity.IdentityIdentifier = IdentityIdentifier

	data, _ := json.Marshal(&identity)
	request.Parameters = data
	err := network.SendRequest(request, conn)
	if err != nil {
		logger.Logger.Error("fail to send request to bc")
		_ = conn.Close()
		return sendRequestFailErr
	}

	res, err := network.GetResponse(conn)
	if err != nil {
		logger.Logger.Error("fail to get response from bc,error:", err)
		_ = conn.Close()
		return getResponseFailErr
	}

	if res.Code != 200 {
		if res.Code == 404 {
			logger.Logger.Warn("user identity not exit")
			return nil
		}

		logger.Logger.Error("send user registry info fail,error:", res.ErrorMsg)
		return errors.New(res.ErrorMsg)
	} else {
		logger.Logger.Info("delete user identity success")
	}

	return nil
}

func GetUserByID(id int) *usermodel.User {
	return userdao.GetUserByID(id)
}

func GetUserByName(name string) *usermodel.User {
	return userdao.GetUserByName(name)
}

func TokenGetPhone(token string) string {
	appid := "300012514176"
	appSecret := "5793CF7709A54D1EBC8FCB4659463C3C"
	msgid := "bed1dc7f6cd645b9be9006ae08040c93"
	systemtime := time.Now().Format("2006010215040512")

	// Create a new request payload
	requestPayload := usermodel.TokenRequest{
		Version:             "2.0",
		Msgid:               msgid, // Replace with an actual unique random string
		Systemtime:          systemtime,
		Strictcheck:         "0",
		Appid:               appid,
		Token:               token,
		Sign:                utils.ToUpperMD5(appid + "2.0" + msgid + systemtime + "0" + token + appSecret),
		Encryptionalgorithm: "",
	}

	// Marshal the request payload to JSON
	jsonData, err := json.Marshal(requestPayload)
	if err != nil {
		fmt.Printf("Error: %s", err)
		return ""
	}
	fmt.Println(string(jsonData))

	// Define the URL endpoint
	url := "https://www.cmpassport.com/unisdk/rsapi/loginTokenValidate"

	// Create a new HTTP POST request
	req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
	if err != nil {
		fmt.Printf("Error: %s", err)
		return ""
	}

	// Set the Content-Type header
	req.Header.Set("Content-Type", "application/json")

	// Execute the HTTP request
	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		fmt.Printf("Error: %s", err)
		return ""
	}
	defer resp.Body.Close()

	// Read the response body
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		fmt.Printf("Error: %s", err)
		return ""
	}
	fmt.Println(string(body))

	// Print the response body to stdout
	//fmt.Println("Response:", string(body))
	var responseData usermodel.ResponseData
	if err := json.Unmarshal(body, &responseData); err != nil {
		log.Fatal(err)
	}

	// 现在你可以访问responseData中的字段了
	log.Println("InResponseTo:", responseData.InResponseTo)
	log.Println("SystemTime:", responseData.SystemTime)
	log.Println("ResultCode:", responseData.ResultCode)
	log.Println("Msisdn:", responseData.Msisdn)
	log.Println("TaskId:", responseData.TaskId)
	return responseData.Msisdn
}

func GetTaskIdByPhone(phone string) string {
	apId := "752261"
	appId := "300012475450"
	appKey := "CD7A3B5E7878FE8E9F79BCFBD689D6FF"

	location, _ := time.LoadLocation("Asia/Shanghai")
	now := time.Now().In(location)
	timestamp := fmt.Sprintf("%s%03d", now.Format("20060102150405"), now.Nanosecond()/1e6)

	traceId := uuid.New().String()
	interfaceVersion := "2.0"
	templateId := "DF20240807163846f0b64a"

	rawData := usermodel.ReqData{
		PhoneNumber:   phone,
		TemplateId:    templateId,
		CallbackUrl:   "http://83q7aj.natappfree.cc/SimAuthCallBack", // TODO 待确定回调url
		MsgType:       "1",
		TemplateParam: "",
		EncVcode:      "",
		ExpandParams:  "",
	}

	// 将 reqData 结构转换为 JSON
	dataJson, err := json.Marshal(rawData)
	if err != nil {
		logger.Logger.Errorf("Error marshaling reqData JSON: %s", err)
		return ""
	}

	reqData, err := utils.EncryptAESWithCBC(dataJson, appKey)

	requestPayload := usermodel.SimRequest{
		ReqData: reqData,
		Sign:    utils.ToMD5(timestamp + traceId + interfaceVersion + appId + reqData + appKey),
	}

	// Marshal the request payload to JSON
	jsonData, err := json.Marshal(requestPayload)
	if err != nil {
		logger.Logger.Errorf("Error: %s", err)
		return ""
	}

	// Define the URL endpoint
	url := "https://www.cmpassport.com/h5/localSimCert/bisSimAuthReq"

	// Create a new HTTP POST request
	req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
	if err != nil {
		logger.Logger.Errorf("Error: %s", err)
		return ""
	}

	// Set the Content-Type header
	req.Header.Set("Content-Type", "application/json;charset=UTF-8")
	req.Header.Set("interfaceVersion", interfaceVersion)
	req.Header.Set("traceId", traceId)
	req.Header.Set("clientEnv", "1")
	req.Header.Set("apId", apId)
	req.Header.Set("appId", appId)
	req.Header.Set("timestamp", timestamp)
	req.Header.Set("host", "www.cmpassport.com")

	// Execute the HTTP request
	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		logger.Logger.Errorf("Error: %s", err)
		return ""
	}
	defer resp.Body.Close()

	// Read the response body
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		logger.Logger.Errorf("Error: %s", err)
		return ""
	}

	var responseData usermodel.SimResponse
	if err := json.Unmarshal(body, &responseData); err != nil {
		logger.Logger.Error("Failed to unmarshal response body:", err)
		return ""
	}

	return responseData.Data.TaskId
}

func GetPhoneForSingleLogin(token string) string {
	version := "1.0"
	msgid := uuid.New().String()
	minappid := minSDKConfig.MinAppid
	systemtime := time.Now().Format("20121227180001165")

	// Create a new request payload
	requestPayload := usermodel.SingleLoginRequest{
		Version:      version,
		Msgid:        msgid,
		Minappid:     minappid,
		Systemtime:   systemtime,
		Expandparams: "",
		Token:        token,
		Sign:         utils.ToUpperMD5(minappid + version + systemtime + token),
	}

	// Marshal the request payload to JSON
	jsonData, err := json.Marshal(requestPayload)
	if err != nil {
		logger.Logger.Errorf("Error: %s", err)
		return ""
	}
	logger.Logger.Info(string(jsonData))

	// Define the URL endpoint
	url := "http://101.200.151.124:33333/getPhone" // TODO 待确认

	// Create a new HTTP POST request
	req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
	if err != nil {
		logger.Logger.Errorf("Error: %s", err)
		return ""
	}

	// Set the Content-Type header
	req.Header.Set("Content-Type", "application/json")

	// Execute the HTTP request
	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		logger.Logger.Errorf("Error: %s", err)
		return ""
	}
	defer resp.Body.Close()

	// Read the response body
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		logger.Logger.Errorf("Error: %s", err)
		return ""
	}
	logger.Logger.Info(string(body))

	var responseData usermodel.SingleLoginResponse
	if err := json.Unmarshal(body, &responseData); err != nil {
		log.Fatal(err)
	}

	// 现在你可以访问responseData中的字段了
	logger.Logger.Info("SystemTime:", responseData.SystemTime)
	logger.Logger.Info("ResultCode:", responseData.ResultCode)
	logger.Logger.Info("Msisdn:", responseData.PhoneNumber)

	key := utils.GenerateKey(minappid + systemtime)
	phone, err := utils.DecryptAESWithECB(responseData.PhoneNumber, key)
	if err != nil {
		logger.Logger.Error("DecryptAESWithECB error:", err)
		return ""
	}
	return phone
}
